<template>
  <div class="about">
    <h1>手写promise</h1>
  </div>
</template>
<script setup>
const p1 = new Promise((resolve, reject) => {
  resolve(1)
})
// console.log(p1, 'p1')

p1.then(res => {
  //   console.log(res, 'res')
})

class myPromise {
  status = 'pedding'
  value = undefined
  reason = undefined
  resolveCallbacks = []
  rejectCallbacks = []
  constructor(fn) {
    const resolve = value => {
      if (this.status === 'pedding') {
        this.status = 'fulfilled'
        this.value = value
        this.resolveCallbacks.forEach(fn => fn(this.value))
      }
    }
    const reject = reason => {
      if (this.status === 'pedding') {
        this.status = 'rejected'
        this.reason = reason
        this.rejectCallbacks.forEach(fn => fn(this.reason))
      }
    }
    try {
      fn(resolve, reject)
    } catch (err) {
      reject(err)
    }
  }
  then(fn1, fn2) {
    fn1 = typeof fn1 === 'function' ? fn1 : v => v
    fn2 = typeof fn2 === 'function' ? fn2 : e => e
    if (this.status === 'fulfilled') {
      return new myPromise((resolve, reject) => {
        try {
          const newVal = fn1(this.value)
          resolve(newVal)
        } catch (err) {
          reject(err)
        }
      })
    }
    if (this.status === 'rejected') {
      return new myPromise((resolve, reject) => {
        try {
          const newReason = fn2(this.reason)
          reject(newReason)
        } catch (err) {
          reject(err)
        }
      })
    }
    if (this.status === 'pedding') {
      return new myPromise((resolve, reject) => {
        this.resolveCallbacks.push(() => {
          try {
            const newVal = fn1(this.value)
            resolve(newVal)
          } catch (err) {
            reject(err)
          }
        })
        this.rejectCallbacks.push(() => {
          try {
            const newReason = fn2(this.reason)
            reject(newReason)
          } catch (err) {
            reject(err)
          }
        })
      })
    }
  }
  catch(fn) {
    return this.then(null, fn)
  }
}
myPromise.resolve = function (value) {
  return new myPromise((resolve, reject) => {
    resolve(value)
  })
}
myPromise.reject = function (reason) {
  return new myPromise((resolve, reject) => {
    reject(reason)
  })
}
myPromise.all = function (promiseList = []) {
  return new Promise((resolve, reject) => {
    const result = [] //存储 promiseList 所有结果
    const length = promiseList.length
    let resolvedCount = 0
    promiseList.forEach(p => {
      p.then(res => {
        result.push(res)
        resolvedCount++
        if (resolvedCount === length) {
          resolve(result)
        }
      }).catch(err => {
        reject(err)
      })
    })
  })
}
myPromise.rece = function (promiseList = []) {
  return new Promise((resolve, reject) => {
    let resolved = false
    promiseList.forEach(p => {
      p.then(
        res => {
          if (!resolved) {
            resolve(res)
            resolved = true
          }
        },
        err => {
          reject(err)
        }
      )
    })
  })
}

const myP1 = new myPromise((resolve, reject) => {
  // resolve(666)
  reject('错误')
})

// myP1.then(
//   res => {
//     console.log(res, 'res2')
//   }
// ).catch(err=>{
//     console.log(err,'err2');
// })

// const myP2 = myPromise.resolve(999)
// myP2.then(res => {
//   console.log(res, 'res3')
// })

let promise1 = new myPromise((resolve, reject) => {
  setTimeout(() => {
    resolve(1)
  }, 2000)
})
let promise2 = new myPromise((resolve, reject) => {
  setTimeout(() => {
    resolve(2)
  }, 1000)
})
let promise3 = new myPromise((resolve, reject) => {
  setTimeout(() => {
    resolve(3)
  }, 3000)
})
myPromise.rece([promise1, promise2, promise3]).then(res => {
  console.log(res)
  //结果为：[1,2,3]
})
</script>
<style></style>
